import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Image;
import java.net.URL;
import java.util.HashMap;
import java.util.Random;
import javax.swing.ImageIcon;

public class Player {
	//////////////////////MAKE THIS CLASS DYNAMIC TO EVERYTHING////////////////////////////////////
	private Animation current;
	private HashMap<String, HashMap> animation;
	private HashMap<String, Animation> left, right;
	
	private float x, y, vx, vy;// position & speed
	private Player opponent;
	private String position;
	private AudioClip punchSound;
	private int health, lastWidth, cumJumpTime;
	private boolean punching, kicking, jumping, ducking;
	private float lastX, startingX, startingY;

	
	
	// CONSTRUCTOR
	public Player(String position, Player opponent, int x, int y) {
		this.opponent = opponent;
		this.health = 100;
		left = new HashMap<String, Animation>();
		right = new HashMap<String, Animation>();
		animation = new HashMap<String, HashMap>();
		initializeAnimations(position);
		punching = false;
		kicking = false;
		jumping = false;
		this.x = x;
		this.y = y;
		this.position = position;
		lastX = this.x;
		startingX = this.x;
		
		//loads punching and kicking sound
		punchSound = Applet.newAudioClip(getClass().getResource("sounds/hit.wav"));
	}
	
	//initializes the animations
	private void initializeAnimations(String position){
		animation.put("left", left);
		animation.put("right", right);
		
		String color;
		if(position.equals("left")){
			color = "blue";
		}else {
			color = "black";
		}
		//left still img
		Image still = new ImageIcon(currDirectory() + "images\\" + color + " player\\left_person.png").getImage();
		Animation stillA = new Animation();
		stillA.addScene(still, 10);
		animation.get("left").put("still", stillA);
		
		//right still img
		still = new ImageIcon(currDirectory() + "images\\" + color + " player\\right_person.png").getImage();
		stillA = new Animation();
		stillA.addScene(still, 10);
		animation.get("right").put("still", stillA);
		
		//adds all the rest of the animations: duck, jump, punch, kick
		java.text.DecimalFormat format = new java.text.DecimalFormat("#0000.###");
		format.setDecimalSeparatorAlwaysShown(false);
		Animation Lduck = new Animation(), Rduck = new Animation(),
			Ljump = new Animation(), Rjump = new Animation(),
			Lpunch = new Animation(), Rpunch = new Animation(), 
			Lkick = new Animation(), Rkick = new Animation();
		
		for (int f = 1; f <= 20; f++) {
			//left pics
			String leftdir = currDirectory() + "images\\" + color+ " player\\left_";
			
			Image img = new ImageIcon(leftdir + "duck\\left_duck" + format.format(f)+".png").getImage();
			Lduck.addScene(img, 26);
			
			img = new ImageIcon(leftdir + "jump\\left_jump" + format.format(f)+".png").getImage();
			Ljump.addScene(img, 52);
			
			img = new ImageIcon(leftdir + "kick\\left_person" + format.format(f)+".png").getImage();
			Lkick.addScene(img, 26);
			
			img = new ImageIcon(leftdir + "punch\\left_punch" + format.format(f)+".png").getImage();
			Lpunch.addScene(img, 26);
			
			//right pics
			String rightdir = currDirectory() + "images\\" + color+ " player\\right_";
			
			img = new ImageIcon(rightdir + "duck\\left_duck" + format.format(f)+".png").getImage();
			Rduck.addScene(img, 26);
			
			img = new ImageIcon(rightdir + "jump\\left_jump" + format.format(f)+".png").getImage();
			Rjump.addScene(img, 52);
			
			img = new ImageIcon(rightdir + "kick\\left_person" + format.format(f)+".png").getImage();
			Rkick.addScene(img, 26);
			
			img = new ImageIcon(rightdir + "punch\\left_punch" + format.format(f)+".png").getImage();
			Rpunch.addScene(img, 26);
		}
		
		animation.get("left").put("duck", Lduck);
		animation.get("left").put("jump", Ljump);
		animation.get("left").put("kick", Lkick);
		animation.get("left").put("punch", Lpunch);
		
		animation.get("right").put("duck", Rduck);
		animation.get("right").put("jump", Rjump);
		animation.get("right").put("kick", Rkick);
		animation.get("right").put("punch", Rpunch);
		
		this.current = (Animation)animation.get(position).get("still");
	}
	
	// change position
	public void update(long timePassed, int screenWidth) {
		lastWidth = this.getWidth();
		lastX = x;
				
		x += vx * timePassed;
		//y += vy * timePassed;
		
		current.update(timePassed);
		if (punching || kicking) {
			//collision test
			if(this.position.equals("left")){
				if((this.getX()+this.getWidth()) >= opponent.getX() && !jumping){
					Random generator = new Random();
					int power = kicking ? 5 :1;
					opponent.hit(generator.nextInt(10)+power);
					punchSound.play();
					punching = false;
					kicking = false;
					x = startingX;
				}
			}else if(this.position.equals("right")){
				if((opponent.getX()+opponent.getWidth()) >= this.getX() && !jumping && !opponent.isJumping()){
					Random generator = new Random(); 
					int power = kicking ? 5 :1;
					opponent.hit(generator.nextInt(10)+power);
					punchSound.play();
					punching = false;
					kicking = false;
					x = startingX;
				}
			}
			
		}
		if(this.position.equals("right")){
			if(this.current != (Animation)animation.get(position).get("still")){
				this.setX(lastX -(this.getWidth()- lastWidth));
			}
		}
		
		//jumping animation
		if(jumping){
			cumJumpTime+=timePassed;
			long t = cumJumpTime;
			y = (float)((63f/67600f)*Math.pow(t-520, 2));
			if(y >= startingY){
				y = startingY;
				jumping = false;
				cumJumpTime = 0;
			}
		}
		
		//STOPS LOOP once it's over
		if(current.finished){
			current = (Animation)animation.get(position).get("still");
			current.start();
			if ((punching || kicking) && !jumping)
				x = startingX;
			punching = false;
			kicking = false;
			
		}
		
	}
	
	//sets the ducking conditions
	public void duck(){
		if (ducking == false){
			this.current = (Animation)animation.get(position).get("duck");
			this.current.start();
			startingY = this.y;
		}
	}
	
	//sets jumping conditions
	public void jump(){
		if(jumping == false){
			this.current = (Animation)animation.get(position).get("jump");
			this.current.start();
			cumJumpTime = 0;
			jumping = true;
			startingY = this.y;
			
		}
	}
	
	//sets punching conditions
 	public void punch(Player opponent) {
		if (position.equals("right") && lastX != startingX){
			lastWidth = 124;
			lastX = startingX;
			x = startingX;
		}else{
			startingX = this.x;
		}
		
		this.current = (Animation)animation.get(position).get("punch");
		this.current.start();
		punching = true;
		this.opponent = opponent;
	}
	
	//sets kicking conditions
	public synchronized void kick(Player opponent){
		if (position.equals("right") &&lastX != startingX){
			lastWidth = 124;
			lastX = startingX;
			x = startingX;
		}else{
			startingX = this.x;
		}
		this.current = (Animation)animation.get(position).get("kick");
		this.current.start();
		kicking = true;
		this.opponent = opponent;
	}

	public void hit(int hit) {
		if(this.health - hit >= 0){
			this.health -= hit;
		}else{
			this.health = 0;
		}
		
	}
	
	// finds folder of the project
	private static String currDirectory() {
		final URL location;
		final String classLocation = Game.class.getName().replace('.', '/')
				+ ".class";
		final ClassLoader loader = Game.class.getClassLoader();
		if (loader == null) {
			return ("Cannot load the class");
		} else {
			location = loader.getResource(classLocation);
			String directory = location.toString().substring(6,
					location.toString().length() - 14);
			directory = directory.replace("%20", " ");
			directory = directory.replace("/", "\\");
			return (directory);
		}
	}
	
	// /// GETTERS and SETTERS ///////
	// get x position
	public float getX() {
		return x;
	}

	// set x position
	public void setX(float x) {
		this.x = x;
	}

	// get y position
	public float getY() {
		return y;
	}

	// set y position
	public void setY(float y) {
		this.y = y;
	}

	// get sprite width
	public int getWidth() {
		return current.getImage().getWidth(null);
	}

	// get sprite height
	public int getHeight() {
		return current.getImage().getHeight(null);
	}

	// get horizontal velocity
	public float getVelocityX() {
		return vx;
	}

	// set horizontal velocity
	public void setVelocityX(float vx) {
		this.vx = vx;
	}

	// get vertical velocity
	public float getVelocityY() {
		return vy;
	}

	// set vertical velocity
	public void setVelocityY(float vy) {
		this.vy = vy;
	}

	// get sprite's image
	public Image getImage() {
		return current.getImage();
	}
	
	//returns health
	public String getHealth(){
		return Integer.toString(health);
	}
	
	//returns whether or not the character is jumping
	public boolean isJumping(){
		return jumping;
	}
}
